﻿Imports System.Globalization
Imports Aricie.DNN.Settings
Imports Aricie.DNN.Modules.ModuleWorkflows.Business
Imports Aricie.DNN.Modules.ModuleWorkflows.Settings
Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Entities.Modules.Definitions
Imports DotNetNuke.Entities.Portals


Namespace Aricie.DNN.Services.Url.FriendlyUrl.Providers

    'todo: current algorithm is smelly (no mid nor tabid will be provided in params)
    Public Class ModuleWorkflowsUrlRewriter
        Implements IUrlRewriterProvider
        Implements IIsActive


        Private Shared _WrappedModuleRewriters As New Dictionary(Of String, UrlProviderInfo)

        Public Function GetModuleRewrites() As List(Of GroupParamsRewrite) Implements IUrlRewriterProvider.GetRewrites

            'ajouter un groupe pour le rootpath

            Dim toReturn As New List(Of GroupParamsRewrite)
            Dim modulesWrapper As ArrayList = NukeHelper.ModuleController.GetModulesByDefinition(NukeHelper.PortalId, Aricie.DNN.Modules.ModuleWorkflows.Constants.Business.WrapperModuleName)

            Dim providerTypesAdded As New List(Of Type)

            For Each moduleName As String In FriendlierUrlConfig.Instance.ModuleUrlProviders.Keys
                Dim mdefId As Integer = NukeHelper.GetModuleDefIdByModuleName(moduleName)
                If mdefId <> -1 Then
                    If ModuleFlowFactory.IsSupportedModuleDef(mdefId) Then
                        Dim wrapperModuleRewriter As UrlProviderInfo = FriendlierUrlConfig.Instance.ModuleUrlProviders(moduleName)
                        Dim provider As IUrlRewriterProvider = wrapperModuleRewriter.GetProvider()
                        If provider IsNot Nothing Then
                            _WrappedModuleRewriters(moduleName) = wrapperModuleRewriter
                            If Not providerTypesAdded.Contains(provider.GetType) Then
                                providerTypesAdded.Add(provider.GetType)
                                If TypeOf provider Is IModulesListUrlRewriterProvider Then

                                    'il faut retrouver tous les modules wrapper 
                                    Dim modules As New List(Of Integer)

                                    For Each objModule As ModuleInfo In modulesWrapper
                                        'Try

                                        Dim wrappedMDefId As Integer = ModuleFlowFactory.GetWrappedModuleDefIdByModule(objModule)
                                        If wrappedMDefId = mdefId Then
                                            modules.Add(objModule.ModuleID)
                                        End If

                                        'Catch ex As Exception
                                        '    DotNetNuke.Services.Exceptions.Exceptions.LogException(New ApplicationException("Error while loading wrapped url provider for module " & objModule.ModuleID.ToString, ex))
                                        'End Try


                                    Next

                                    If modules.Count > 0 Then
                                        Dim modulesListProvider As IModulesListUrlRewriterProvider = DirectCast(provider, IModulesListUrlRewriterProvider)

                                        ImportProviders(modulesListProvider.GetRewrites(modules), toReturn)

                                    End If
                                Else
                                    ImportProviders(provider.GetRewrites(), toReturn)
                                End If
                            End If
                        End If
                    End If
                End If
            Next

            Dim categoryRootPath As New GroupParamsRewrite("CategoryRootPath", "L'alias personalisé en fonction de la catégorie.", RewriteType.SubPath)
            categoryRootPath.UrlParams.Add(UrlParam.TabId, ParamNature.NonExclusive)
            categoryRootPath.UrlParams.Add(UrlParam.ModuleId, ParamNature.NonExclusive)
            categoryRootPath.UrlParams.Add(UrlParam.FromSyntax("itemid"), ParamNature.NonExclusive)
            categoryRootPath.UrlParams.Add(UrlParam.FromSyntax("propertyid"), ParamNature.NonExclusive)

            toReturn.Add(categoryRootPath)

            Return toReturn

        End Function

        Private Sub ImportProviders(ByVal source As IList(Of GroupParamsRewrite), ByRef destination As IList(Of GroupParamsRewrite))
            For Each paramRewrite As GroupParamsRewrite In source

                If Not paramRewrite.UrlParams.ContainsKey(UrlParam.TabId) Then
                    paramRewrite.UrlParams.Add(UrlParam.TabId, ParamNature.NonExclusive Or ParamNature.Optional)
                End If
                If Not paramRewrite.UrlParams.ContainsKey(UrlParam.ModuleId) Then
                    paramRewrite.UrlParams.Add(UrlParam.ModuleId, ParamNature.NonExclusive Or ParamNature.Optional)
                End If
                destination.Add(paramRewrite)
            Next
        End Sub

        Public Function RewriteParams(ByVal groupName As String, ByVal objRewriteType As RewriteType, _
                                       ByVal params As Dictionary(Of UrlParam, String), ByVal behaviour As FriendlierUrlStrategy) As GroupRewriteResult _
            Implements IUrlRewriterProvider.RewriteParams

            Dim toReturn As New GroupRewriteResult()
            Dim provider As IUrlRewriterProvider
            provider = GetProvider(groupName, params)


            Select Case groupName.ToLowerInvariant
                Case "categoryrootpath"
                    Dim rootPath As String = String.Empty

                    If TypeOf provider Is ICategoryUrlRewriterProvider Then

                        Dim categoryProvider As ICategoryUrlRewriterProvider = DirectCast(provider, ICategoryUrlRewriterProvider)
                        Dim categoryId As Integer = categoryProvider.GetCategory(params)

                        If categoryId > 0 Then
                            Dim wfSettings As WorkflowSettings = SettingsController.GetModuleSettings(Of WorkflowSettings)(SettingsScope.PortalSettings, NukeHelper.PortalId)


                            If wfSettings.CategoriesSettings.PortalAliasesCategories.ContainsKey(categoryId) Then
                                Dim portalAliasId As Integer = wfSettings.CategoriesSettings.PortalAliasesCategories(categoryId)
                                Dim portalAlias As PortalAliasInfo = NukeHelper.PortalAliasByPortalAliasId(portalAliasId)

                                If portalAlias IsNot Nothing Then
                                    rootPath = portalAlias.HTTPAlias
                                End If
                            End If
                        End If
                    End If

                    If String.IsNullOrEmpty(rootPath) Then
                        'valeur par défaut
                        rootPath = NukeHelper.PortalSettings.PortalAlias.HTTPAlias
                    End If

                    toReturn.RewriteValue = rootPath

                Case Else
                    Return provider.RewriteParams(groupName, objRewriteType, params, behaviour)
            End Select

            Return toReturn
        End Function


        Private Function GetProvider(ByVal groupName As String, ByVal params As Dictionary(Of UrlParam, String)) As IUrlRewriterProvider

            Dim moduleName As String = ""

            Dim mid As Integer = -1
            Dim midParam As UrlParam = UrlParam.ModuleId
            If params.ContainsKey(midParam) Then
                mid = Integer.Parse(params(midParam))
            End If
            If mid <> -1 Then
                Dim mDefid As Integer = ModuleFlowFactory.GetWrappedModuleDefIdByModuleId(mid)
                If mDefid <> -1 Then
                    moduleName = NukeHelper.GetDesktopModuleByModuleDefId(mDefid).ModuleName
                End If
            End If

            If moduleName = "" Then

                Dim tabId As Integer = -1
                If params.ContainsKey(UrlParam.TabId) Then
                    tabId = Integer.Parse(params(UrlParam.TabId))
                End If
                moduleName = FriendlierUrlContext.Instance.FriendlierUrlPortalSettings.FindModuleName(params, tabId, New Converter(Of ModuleInfo, String)(AddressOf ModuleFlowFactory.GetWrappedModuleNameByModule))

                'Dim moduleIdentifiers As Dictionary(Of UrlParam, List(Of String)) = FriendlierUrlContext.Instance.FriendlierUrlPortalSettings.GetModuleIdentifiers
                'For Each param As UrlParam In params.Keys
                '    'paramName = paramName.ToLowerInvariant

                '    If moduleIdentifiers.ContainsKey(param) Then
                '        If moduleIdentifiers(param).Count > 1 Then

                '            If tabId <> -1 Then
                '                'Dim mc As New ModuleController

                '                For Each objModule As ModuleInfo In NukeHelper.ModuleController.GetTabModules(tabId).Values
                '                    If WorkflowController.IsWorkflowModule(objModule.ModuleDefID) Then
                '                        Dim mDefId As Integer = ModuleFlowFactory.GetWrappedModuleDefIdByModule(objModule)
                '                        'Dim wrapperSettings As WrapperSettings = SettingsController.GetModuleSettings(Of WrapperSettings)(SettingsScope.ModuleSettings, objModule.ModuleID)
                '                        Dim desktopMod As DesktopModuleInfo = NukeHelper.GetDesktopModuleByModuleDefId(mDefId)

                '                        If desktopMod IsNot Nothing AndAlso moduleIdentifiers(param).Contains(desktopMod.ModuleName) Then
                '                            moduleName = desktopMod.ModuleName
                '                            Exit For
                '                        End If

                '                    ElseIf moduleIdentifiers(param).Contains(objModule.ModuleName) Then
                '                        moduleName = objModule.ModuleName
                '                        Exit For
                '                    End If
                '                Next
                '            End If
                '        Else
                '            moduleName = moduleIdentifiers(param)(0)
                '        End If
                '        If moduleName <> "" Then
                '            Exit For
                '        End If
                '    End If
                'Next
            End If
            If moduleName <> "" Then
                If Not _WrappedModuleRewriters.ContainsKey(moduleName) Then
                    Throw New InvalidOperationException(String.Format("WrappedModule {0} does not provide the required url rewriter", moduleName))
                End If
                Return _WrappedModuleRewriters(moduleName).GetProvider
            End If

            For Each moduleName In _WrappedModuleRewriters.Keys
                For Each paramRewrite As GroupParamsRewrite In _WrappedModuleRewriters(moduleName).GetProvider.GetRewrites
                    If paramRewrite.GroupName.ToLowerInvariant = groupName.ToLowerInvariant Then
                        Return _WrappedModuleRewriters(moduleName).GetProvider
                    End If
                Next
            Next

            Dim inputparams As String = ""
            For Each objParam As UrlParam In params.Keys
                inputparams &= objParam.SyntaxOptions(0) & "=" & params(objParam) & " ,"
            Next
            Throw New InvalidOperationException(String.Format("wrappedModule rewriter not identified, for groupname {0} anda params {1}", groupName, inputparams))

        End Function


        Public ReadOnly Property IsActive As Boolean Implements IIsActive.IsActive
            Get
                Return False ' par défaut on active jamais le provider
            End Get
        End Property
    End Class
End Namespace


